package com.espirit.eap.util.tagAdaptor;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.espirit.eap.manager.I18n;
import com.espirit.eap.manager.I18nService;
import com.espirit.eap.pagelayout.AvabButton;
import com.espirit.eap.pagelayout.Element;
import com.espirit.eap.pagelayout.FunctionButton;
import com.espirit.eap.pagelayout.Layout;
import com.espirit.eap.pagelayout.LinkedButton;
import com.espirit.eap.pagelayout.Model;
import com.espirit.eap.pagelayout.PageCache;
import com.espirit.eap.pagelayout.TagInfo;
import com.espirit.eap.util.Functions;
import com.googlecode.cswish.Config;
import com.googlecode.cswish.util.FrameConstant;

@Service
public class TagAvabButtonAdaptor implements TagElementAdaptor<AvabButton> {
	
	@Resource
	private Functions functions;
	
	@Resource
	private Config config;
	
	@Resource
	private I18nService i18nService;
	
	@Resource
	private TagAdaptorUtil tagAdaptorUtil;

	private Map<String, String> commonMethods = new LinkedHashMap<String, String>();
	
	public TagAvabButtonAdaptor() {
		commonMethods.put("_add", "_addRecord(this)");
		commonMethods.put("_update", "_updateRecord(this)");
		commonMethods.put("_search", "searchRecord(this)");
		commonMethods.put("add", "_addRecord(this)");
		commonMethods.put("update", "_updateRecord(this)");
		commonMethods.put("search", "searchRecord(this)");
		commonMethods.put("delete", "deleteRecord(this)");
		commonMethods.put("deleteList", "deleteListRecord(this)");
		commonMethods.put("print", "printRecord(this)");
		commonMethods.put("export", "exportRecord(this)");
		commonMethods.put("_goNext", "_goNextRecord(this)");
		commonMethods.put("_approve", "_approveRecord(this)");
		commonMethods.put("close", "closeRecord(this)");
		
		commonMethods.put("save", "submitInputPage(this)");
		commonMethods.put("cancel", "closeInputPage(this)");
	}
	
	
	
	@Override
	public TagInfo getTagProperties(Layout root, AvabButton avabButton, Map<String, Object> context) {
		TagInfo tagInfo = new TagInfo(true);
		String tagName = null;
		Map<String, Object> properties = tagInfo.getTagProperties();
		String name = tagAdaptorUtil.getName(avabButton);
		
		if (avabButton instanceof LinkedButton) {
			properties.put("name", name);
			LinkedButton linkedButton = (LinkedButton)avabButton;
			tagName = "linkedbutton";
			
			// name width image
			//String statusProperty = linkedButton.getStatusProperty();		// TODO: remove this property?
			// NOTICE: the image root must be in config.imgDir
			properties.put("image", config.getImgDir() + linkedButton.getImage());
			if (linkedButton.getModel() != null) {
				String url = functions.linkModelNoBase(linkedButton.getModel(), linkedButton.getMethod()) + "?model.id=";
				properties.put("url", url);
			}
		} else {
			properties.put("name", name);
			
			// TODO: merge 'ebutton' and 'button'?
			tagName = (avabButton.getModel() == null && avabButton.getMethod() == null && avabButton.getTarget() == null)
				? "button" : "ebutton";
			properties.put("method", avabButton.getMethod());
			properties.put("submit", avabButton.getSubmit());
			
			// url, target, params
			String url;
			if (avabButton.getModel() != null) {
				url = functions.linkModelNoBase(avabButton.getModel(), avabButton.getMethod());
				properties.put("url", url);
			}
			if (avabButton.getTarget() != null) {
				// find the target id according to the tag name
				String target = avabButton.getTarget();
				// FIXME: load the newest version of the target?
				
				properties.put("target", target);
				
				StringBuilder parameters = new StringBuilder();
				parameters.append(FrameConstant.PARAM_RESULTCODE) 
					.append("=$result&").append(FrameConstant.PARAM_TEMPLATE).append("=").append(target).append(",");
				properties.put("params", parameters.toString());
			}
		}
		
		// label
		String i18n = avabButton.getI18n();
		if (i18n != null) {
			properties.put("label", i18n);
		}
		properties.put("positionCol", avabButton.getPositionCol());
		
		// extra properties
		// btnProperties, be compatible with Builder file 
		Map<String, String> btnProperties = avabButton.getExProperties();
		if (btnProperties != null) {
			properties.putAll(btnProperties);
		}
		
		tagInfo.setTagName(tagName);
		return tagInfo;
	}
	
	@Override
	public String getTagName(AvabButton sectionElement) {
		AvabButton avabButton = sectionElement;
		
		if (avabButton instanceof LinkedButton) {
			return "linkedbutton";
		} else {
			String tagName = (avabButton.getModel() == null && avabButton.getMethod() == null && avabButton.getTarget() == null)
					? "button" : "ebutton";
			return tagName;
		}
	}
	
	@Override
	public AvabButton updateToElement(Map<String, String> tagProperties, AvabButton existed, Map<String, Object> context, PageCache pageCache) {
		AvabButton avabButton = (AvabButton)existed;
		Map<String, String> properties = new HashMap<String, String>(tagProperties);
		if (avabButton instanceof LinkedButton) {
			LinkedButton linkedButton = (LinkedButton)avabButton;
			
			//image --> skip base + config.imgDir
			String image = properties.get("image");
			String prefix = config.getImgDir();
			if (image.startsWith(prefix)) {
				image = image.substring(prefix.length());
				properties.put("image", image);
			}
		}
		
		// label
		tagAdaptorUtil.updateLabel(properties, avabButton, pageCache);
		
		// the other standard property
		Map<String, Object> defaultTagProperties = (Map<String, Object>) context.get(DEFAULT_TAG_PROP);
		tagAdaptorUtil.updateElement(properties, defaultTagProperties, existed);
		return existed;
	}

	@Override
	public Element addElement(Element parent, String tagName, Map<String, Object> properties, PageCache pageCache) {
		Layout root = pageCache.getLayout();
		// if the parent isn't container, use the parent's parent
		Integer index = pageCache.increaseMaxId();
				
		// create button		
		String name = (String)properties.get(NAME);
		if (name == null || name.length() == 0) {
			name = tagAdaptorUtil.createName("button", "" + (index+1));
		} else {
			// 
		}
		
		AvabButton button;
		Model model = pageCache.getModel();
		Map<String, String> exProperties = new HashMap<String, String>();
		if ("button".equals(tagName)) {
			button = model.getAvabButton(name);
			if (button == null) {
				button = new AvabButton();
			} else {
				if (button.getExProperties() != null) {
					exProperties.putAll(button.getExProperties());
				}
			}
			// TODO: Clean method, add extra parameter url
			
		} else if ("ebutton".equals(tagName)) {
			button = new FunctionButton();
			button.setModel(model.getName());
			button.setMethod(name);
		} else {
			LinkedButton linkedButton = new LinkedButton();
			//linkedButton.setStatusProperty(name);
			button = linkedButton;
			// set a demo link
			String url = functions.linkModelNoBase(pageCache.getModel().getName(), name);
			linkedButton.addExProperty("url", url);
		}
		
		// common property
		button.setTagName(tagName);
		button.setId(-(index+1));
		button.setName(name);
		
		// label position
		Element sectionElement = tagAdaptorUtil.createSectionElement(root, parent, button);
		
		sectionElement.setId(-index);
		String onclickEvent = commonMethods.get(name);
		if (onclickEvent != null) {
			// event
			exProperties.put("onclick", onclickEvent);
			
			// i18n
			I18n commonI18n = i18nService.getI18n("action." + name, false);
			if (commonI18n != null) {
				sectionElement.setI18n(commonI18n.getCnName());
			}
			
			String method;
			if ("save".equals(name)) {
				if ("_add".equals(pageCache.getInvoker().methodName)) {
					method = "add";
				} else {
					method = "update";
				}
			} else if ("cancel".equals(name)) {
				method = null;
			} else {
				method = name;
			}
			if (method != null) {
				String permissionUrl = functions.linkModelNoBase(pageCache.getModel().getName(), method);
				exProperties.put("url", permissionUrl);
			}
		}
		sectionElement.setExProperty(exProperties);
		
		if (sectionElement.getI18n() == null) {
			sectionElement.setI18n(name);
		}
		
		Integer positionCol = (Integer) properties.get(POSITION_COL);
		Integer positionRow = (Integer) properties.get(POSITION_ROW);
		sectionElement.setPositionCol(positionCol);
		sectionElement.setPositionRow(positionRow);
		return sectionElement;
	}

	public boolean hasCommonMethod(String name) {
		return commonMethods.containsKey(name);
	}


	@Override
	public void deleteElement(Element parent, AvabButton existed, PageCache pageCache) {
		
	}

	public Collection<String> getCommonMethods() {
		return commonMethods.keySet();
	}
};